﻿using System;
using System.IO;
using System.Reflection;
using System.Windows.Forms;

namespace Outlook.WorkItems.Extension.Controls
{
    public partial class TeamReportViewerForm : Form
    {
        private Control _reportViewer2005;
        private string _currentReportVersion;

        public string FilePath { get; set; }

        public TeamReportViewerForm()
        {
            InitializeComponent();
        }

        private void TeamReportViewerForm_Load(object sender, EventArgs e)
        {
            if (DesignMode) 
                return;
            teamTreeViewUC1.ShowReport = true;
            teamTreeViewUC1.ShowDocumentLibrairies = false;
            teamTreeViewUC1.treeView1.AfterSelect += treeView1_AfterSelect;
            teamTreeViewUC1.InitTreeView();
        }

        private void reportViewer1_ReportExport(object sender, Microsoft.Reporting.WinForms.ReportExportEventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            try
            {
                e.Cancel = true;
                string mimeType;
                string encoding;
                string fileNameExtension;
                string deviceInfo = e.DeviceInfo;

                Microsoft.Reporting.WinForms.Warning[] warnings;

                string[] streams;
                byte[] renderedBytes;

                ReportNode reportNode = teamTreeViewUC1.treeView1.SelectedNode as ReportNode;

                renderedBytes = reportViewer1.ServerReport.Render(e.Extension.Name, deviceInfo, out mimeType, out encoding, out fileNameExtension, out streams, out warnings);
                string folderPath = Path.GetTempPath();
                string fileName = reportNode.Text + "." + fileNameExtension;
                FilePath = folderPath + fileName;
                File.WriteAllBytes(FilePath, renderedBytes);


                DialogResult = DialogResult.OK;
                Close();
            }
            catch (Exception ex)
            {
                using (var frm = new ErrorForm(ex))
                {
                    frm.ShowDialog();
                }
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            try
            {
                ReportNode reportNode = e.Node as ReportNode;
                if (reportNode == null)
                    return;

                if (reportNode.ReportVersion != _currentReportVersion)
                {
                    _currentReportVersion = reportNode.ReportVersion;
                    if (_currentReportVersion == ReportingServicesVersion.Reporting2005)
                        LoadReportViewer2005();
                    else
                        LoadReportViewer2008();
                }

                if (_currentReportVersion == ReportingServicesVersion.Reporting2008)
                {
                    reportViewer1.Reset();
                    reportViewer1.CancelRendering(0);
                    reportViewer1.ServerReport.ReportPath = reportNode.ReportItem.Path;
                    reportViewer1.ServerReport.ReportServerUrl = new Uri(reportNode.ReportServer);
                    reportViewer1.RefreshReport();
                }
                else
                {
                    LoadReportViewer2005();
                    ChangeReport2005(reportNode);
                }
            }
            catch (Exception ex)
            {
                using (var frm = new ErrorForm(ex))
                {
                    frm.ShowDialog();
                }
            }
        }

        private void LoadReportViewer2008()
        {
            splitContainer1.Panel2.Controls.Clear();
            splitContainer1.Panel2.Controls.Add(reportViewer1);
        }

        private void LoadReportViewer2005()
        {
            splitContainer1.Panel2.Controls.Clear();
            var reportViewerAssembly = Assembly.Load("Microsoft.ReportViewer.WinForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
            Type tReportViewer = reportViewerAssembly.GetType("Microsoft.Reporting.WinForms.ReportViewer");
            Type tEventHandler = reportViewerAssembly.GetType("Microsoft.Reporting.WinForms.ExportEventHandler");


            EventInfo eventInfo = tReportViewer.GetEvent("ReportExport");

            _reportViewer2005 = reportViewerAssembly.CreateInstance("Microsoft.Reporting.WinForms.ReportViewer") as Control;

            Type type = eventInfo.EventHandlerType;

            MethodInfo method = GetType().GetMethod("reportViewer1_ReportExport2005", BindingFlags.NonPublic | BindingFlags.Instance);
            Delegate handler = Delegate.CreateDelegate(type, this, method);

            eventInfo.AddEventHandler(_reportViewer2005, handler);
            splitContainer1.Panel2.Controls.Add(_reportViewer2005);
            _reportViewer2005.Dock = DockStyle.Fill;
        }

        private void ChangeReport2005(ReportNode node)
        {
            Type tReportViewer = _reportViewer2005.GetType();
            PropertyInfo pServerReport = tReportViewer.GetProperty("ServerReport");

            Type tServerReport = pServerReport.PropertyType;
            PropertyInfo pReportPath = tServerReport.GetProperty("ReportPath");
            pReportPath.SetValue(pServerReport.GetValue(_reportViewer2005, null), node.ReportItem.Path, null);

            PropertyInfo pReportServerUrl = tServerReport.GetProperty("ReportServerUrl");
            pReportServerUrl.SetValue(pServerReport.GetValue(_reportViewer2005, null), new Uri(node.ReportServer), null);

            PropertyInfo pProcessingMode = tReportViewer.GetProperty("ProcessingMode");
            pProcessingMode.SetValue(_reportViewer2005, 1, null);

            MethodInfo mRefreshMethod = tReportViewer.GetMethod("RefreshReport", BindingFlags.NonPublic | BindingFlags.Instance);
            mRefreshMethod.Invoke(_reportViewer2005, new object[] { 0 });
        }


        private void reportViewer1_ReportExport2005(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;
            try
            {
                var reportViewerAssembly = Assembly.Load("Microsoft.ReportViewer.WinForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");

                Type tEventArgs = reportViewerAssembly.GetType("Microsoft.Reporting.WinForms.ReportExportEventArgs");

                var pCancel = tEventArgs.GetProperty("Cancel");
                pCancel.SetValue(e, true, null);

                var pExtension = tEventArgs.GetProperty("Extension");
                var pName = pExtension.PropertyType.GetProperty("Name");
                string reportType = pName.GetValue(pExtension.GetValue(e, null), null) as string;

                var pDeviceInfo = tEventArgs.GetProperty("DeviceInfo");
                string deviceInfo = pDeviceInfo.GetValue(e, null) as string;

                var pServerReport = _reportViewer2005.GetType().GetProperty("ServerReport");

                MethodInfo mRender = null;
                foreach (var item in pServerReport.PropertyType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
                {
                    if (item.Name == "Render" && item.GetParameters().Length == 7)
                        mRender = item;
                }

                string mimeType = null;
                string encoding = null;
                string fileNameExtension = null;


                Microsoft.Reporting.WinForms.Warning[] warnings = null;

                string[] streams = null;
                byte[] renderedBytes = null;

                ReportNode reportNode = teamTreeViewUC1.treeView1.SelectedNode as ReportNode;

                object[] parameters = new object[] { reportType, deviceInfo, mimeType, encoding, fileNameExtension, streams, warnings };

                renderedBytes = mRender.Invoke(pServerReport.GetValue(_reportViewer2005, null), parameters) as byte[];
                //renderedBytes = reportViewer1.ServerReport.Render(e.Extension.Name, deviceInfo, out mimeType, out encoding, out fileNameExtension, out streams, out warnings);
                string folderPath = System.IO.Path.GetTempPath();
                string fileName = reportNode.Text + "." + parameters[4];
                FilePath = folderPath + fileName;
                File.WriteAllBytes(FilePath, renderedBytes);


                DialogResult = DialogResult.OK;
                Close();
            }
            catch (Exception ex)
            {
                using (var frm = new ErrorForm(ex))
                {
                    frm.ShowDialog();
                }
            }
            finally
            {
                Cursor = Cursors.Default;
            }
        }
    }
}